package com.brtbeacon.wx.demo.mapview;

import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.webkit.JavascriptInterface;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

import org.altbeacon.beacon.Beacon;
import org.altbeacon.beacon.BeaconConsumer;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.BeaconParser;
import org.altbeacon.beacon.RangeNotifier;
import org.altbeacon.beacon.Region;
import org.json.JSONArray;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;

public class CustomWebViewActivity extends AppCompatActivity implements BeaconConsumer {

    public static final  String PARAM_URL = "param_url";
    public static final String IBEACON_FORMAT = "m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24";
    public static final String IBEACON_REGION = "992C9DFD-2688-4FF2-B69D-3627EEC8C8A3";
    public final static int GEO_FENCING_PERMISSION_CODE = 999;

    private WebView webView;
    private BeaconManager beaconManager;
    private SensorManager sm = null;
    private Sensor orientationSensor = null;
    private double rotateDegree = 0;
    private boolean webScanTurnOn = false;  // 页面是否调用蓝牙扫描功能
    private boolean isBeaconManagerInit = false;
    private int rssiThreshold = -85;

    private java.text.DecimalFormat df_accuracy = new java.text.DecimalFormat("0.000000");
    private java.text.DecimalFormat df_heading = new java.text.DecimalFormat("0.0000");
    private long lastHeadingTime = 0;

    public static void startActivity(Context ctxt, String url) {
        Intent intent = new Intent(ctxt, CustomWebViewActivity.class);
        intent.putExtra(PARAM_URL, url);
        ctxt.startActivity(intent);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_custom_web_view);

        //  初始化WebView控件
        webView = findViewById(R.id.webView);
        WebSettings webSettings = webView.getSettings();
        webSettings.setDomStorageEnabled(true);
        webSettings.setJavaScriptEnabled(true);
        webSettings.setGeolocationEnabled(true);
        webSettings.setAllowUniversalAccessFromFileURLs(true);
        webSettings.setMediaPlaybackRequiresUserGesture(false);

        webView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, final String url) {
                //view.loadUrl(url);
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        CustomWebViewActivity.startActivity(CustomWebViewActivity.this, url);
                    }
                });
                return true;
            }
        });

        //  绑定智石JS接口
        webView.addJavascriptInterface(zsJavascriptInterface, "zs");

        //  初始化设备方向监听
        sm = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
        orientationSensor = sm.getDefaultSensor(Sensor.TYPE_ORIENTATION);

        //  初始化iBeacon扫描服务
        beaconManager = BeaconManager.getInstanceForApplication(this);
        beaconManager.setUseTrackingCache(true);
        beaconManager.setMaxTrackingAge(8000);
        beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout(IBEACON_FORMAT));
        beaconManager.bind(this);

        //  加载目标网页
        String url = getIntent().getStringExtra(PARAM_URL);
        if (!TextUtils.isEmpty(url)) {
            webView.loadUrl(url);
        }
    }

    @Override
    protected void onDestroy() {
        isBeaconManagerInit = false;
        webScanTurnOn = false;
        stopBeaconRanging();
        if (beaconManager != null) {
            beaconManager.unbind(this);
        }
        super.onDestroy();
    }

    @Override
    protected void onPause() {
        super.onPause();
        sm.unregisterListener(sensorEventListener);
    }

    @Override
    protected void onResume() {
        super.onResume();
        sm.registerListener(sensorEventListener, orientationSensor, SensorManager.SENSOR_DELAY_GAME);

        List<String> permissionList = getRequestPermissions();
        if (!permissionList.isEmpty()) {
            requestPermissions(permissionList);
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            if(webView.canGoBack()) {
                webView.goBack();
                return true;
            }
            finish();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    //  将偏北角数据传入加载的H5页面
    private void updateWebDeviceRotateDegree(final double value) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                rotateDegree = value;
                if (!webScanTurnOn)
                    return;
                long currentHeadingTime = Calendar.getInstance().getTimeInMillis();
                //  250ms更新一次页面中的设备方向数据
                if (currentHeadingTime - lastHeadingTime >= 250) {
                    lastHeadingTime = currentHeadingTime;
                    webView.evaluateJavascript("javascript:on_app_heading_callback(" + df_heading.format(rotateDegree) + ");", null);
                }
            }
        });
    }

    //  将扫描到的Beacon数据传入到加载的H5页面
    private void updateWebRangingBeacons(final List<Beacon> beaconList) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                try {
                    JSONObject jsonResult = new JSONObject();
                    JSONArray jsonBeacons = new JSONArray();
                    for (Beacon beacon : beaconList) {

                        if (beacon.getRssi() <= rssiThreshold)
                            break;

                        if (beacon.getRssi() >= 0)
                            continue;

                        JSONObject jsonBeacon = new JSONObject();
                        jsonBeacon.put("uuid", beacon.getId1().toString());
                        jsonBeacon.put("major", beacon.getId2().toString());
                        jsonBeacon.put("minor", beacon.getId3().toString());
                        jsonBeacon.put("rssi", String.valueOf(beacon.getRssi()));
                        jsonBeacon.put("accuracy", df_accuracy.format(beacon.getDistance()));
                        jsonBeacon.put("heading", Float.valueOf(df_heading.format(rotateDegree)));
                        jsonBeacon.put("proximity", "1");
                        jsonBeacons.put(jsonBeacon);
                    }

                    jsonResult.put("beacons", jsonBeacons);
                    webView.evaluateJavascript("javascript:on_brtbeacon_beacon_search(" + jsonResult.toString() + ");", null);
                } catch (Exception e) { }
            }
        });
    }

    private SensorEventListener sensorEventListener = new SensorEventListener() {

        @Override
        public void onSensorChanged(SensorEvent event) {
            int sensorType = event.sensor.getType();
            switch (sensorType) {
                case Sensor.TYPE_ORIENTATION: {
                    updateWebDeviceRotateDegree(event.values[0]);
                    break;
                }

                default:
                    return;
            }

        }

        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {

        }
    };

    private Object zsJavascriptInterface = new Object() {

        @JavascriptInterface
        public void share(final String json) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    try {
                        JSONObject jsonObject = new JSONObject(json);
                        String title = jsonObject.getString("title");
                        String imgUrl = jsonObject.getString("imgUrl");
                        String desc = jsonObject.getString("desc");
                        String link = jsonObject.getString("link");

                        Intent intent = new Intent(Intent.ACTION_SEND);
                        intent.setType("text/html");
                        intent.putExtra(Intent.EXTRA_SUBJECT, title);
                        intent.putExtra(Intent.EXTRA_TEXT, desc + " " + link);
                        startActivity(Intent.createChooser(intent, "分享到"));
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        @JavascriptInterface
        public void detail(final String json) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {

                }
            });
        }

        @JavascriptInterface
        public void bleEnable() {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
                    int state = 0;
                    if (bluetoothAdapter == null) {
                        state = 2;
                    } else if (!bluetoothAdapter.isEnabled()) {
                        bluetoothAdapter.enable();
                    }
                    webView.evaluateJavascript("javascript:on_app_ble_enable_callback(" + state + ");", null);
                    if (!webScanTurnOn) {
                        webScanTurnOn = true;
                        startBeaconRanging();
                    }
                }
            });
        }
    };

    @Override
    public void onBeaconServiceConnect() {
        beaconManager.removeAllRangeNotifiers();
        beaconManager.addRangeNotifier(rangeNotifier);
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                isBeaconManagerInit = true;
                startBeaconRanging();
            }
        });
    }

    /**
     *  开启Beacon扫描
     */
    private void startBeaconRanging() {
        if (!isBeaconManagerInit)
            return;
        if (!webScanTurnOn)
            return;
        try {
            beaconManager.startRangingBeaconsInRegion(rangeRegion);
        } catch (Exception e) { }
    }

    /**
     *  关闭Beacon扫描
     */
    private void stopBeaconRanging() {
        if (beaconManager != null) {
            try {
                beaconManager.stopRangingBeaconsInRegion(rangeRegion);
            } catch (Exception e) { }
        }
    }

    private RangeNotifier rangeNotifier = new RangeNotifier() {
        @Override
        public void didRangeBeaconsInRegion(Collection<Beacon> collection, Region region) {
            final List<Beacon> beaconList = new ArrayList<>(collection);
            Collections.sort(beaconList, new Comparator<Beacon>() {
                @Override
                public int compare(Beacon beaconLeft, Beacon beaconRight) {
                    return beaconRight.getRssi() - beaconLeft.getRssi();
                }
            });
            updateWebRangingBeacons(beaconList);
        }
    };

    private Region rangeRegion = new Region(IBEACON_REGION, null, null, null);


    private List<String> getRequestPermissions() {
        List<String> permissions = new LinkedList<>();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {//判断当前系统的SDK版本是否大于23
            for (String permssion: permissionsNeedCheck) {
                if(ActivityCompat.checkSelfPermission(this, permssion) != PackageManager.PERMISSION_GRANTED) {
                    permissions.add(permssion);
                }
            }
        }
        return permissions;
    }

    private void requestPermissions(List<String> permissions) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            requestPermissions(permissions.toArray(new String[0]), GEO_FENCING_PERMISSION_CODE);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            // requestCode即所声明的权限获取码，在requestPermissions时传入
            case GEO_FENCING_PERMISSION_CODE:
                boolean isAllGrant = true;
                for (int grantResult: grantResults) {
                    if (grantResult != PackageManager.PERMISSION_GRANTED) {
                        isAllGrant = false;
                        break;
                    }
                }
                if (!isAllGrant) {
                    Toast.makeText(getApplicationContext(), "定位权限申请失败，请手动前往设置开启", Toast.LENGTH_SHORT).show();
                }
                break;
            default:
                break;
        }
    }

    private static final List<String> permissionsNeedCheck;
    static {
        permissionsNeedCheck = new LinkedList<>();
        permissionsNeedCheck.add(android.Manifest.permission.ACCESS_FINE_LOCATION);
        permissionsNeedCheck.add(android.Manifest.permission.ACCESS_COARSE_LOCATION);
    }
}
